package org.duncan.sjge.events;

import java.util.HashSet;
import java.util.Set;
import org.duncan.sjge.interfaces.Creatable;
import org.duncan.sjge.interfaces.Destroyable;
import org.duncan.sjge.interfaces.Renderable;
import org.duncan.sjge.interfaces.Updatable;

/**
 *
 * @author Duncan
 */
public class GameManager {
    private final Set<CreatePair> mCreatables    = new HashSet<>();
    private final Set<Renderable> mRenderables   = new HashSet<>();
    private final Set<Updatable> mUpdatables     = new HashSet<>();
    private final Set<DestroyPair> mDestroyables = new HashSet<>();
    
    private class CreatePair {
        public Creatable mEntity;
        public CreateEvent mEvent;
    }
    
    private class DestroyPair {
        public Destroyable mEntity;
        public DestroyEvent mEvent;
    }
    
    public void addCreatable(final Creatable create, final CreateEvent ev) {
        if (create != null) {
            final CreatePair pair = new CreatePair();
            pair.mEntity = create;
            pair.mEvent = ev;
            mCreatables.add(pair);
        }
    }
    
    public void addRenderable(final Renderable render) {
        if (render != null) mRenderables.add(render);
    }
    
    public void addUpdatable(final Updatable update) {
        if (update != null) mUpdatables.add(update);
    }
    
    public void addDestroyable(final Destroyable destroy, final DestroyEvent ev) {
        if (destroy != null) {
            final DestroyPair pair = new DestroyPair();
            pair.mEntity = destroy;
            pair.mEvent = ev;
            mDestroyables.add(pair);
        }
    }
    
    public void removeRenderable(final Renderable render) {
        if (render != null) mRenderables.remove(render);
    }
    
    public void removeUpdatable(final Updatable update) {
        if (update != null) mUpdatables.remove(update);
    }
    
    public void callCreate() {
        for (final CreatePair pair : mCreatables) {
            pair.mEntity.onCreate(pair.mEvent);
            addUpdatable(pair.mEntity.getUpdatable());
            addRenderable(pair.mEntity.getRenderable());
        }
        
        mCreatables.clear();
    }
    
    public void callUpdate(final UpdateEvent ev) {
        for (final Updatable entity : mUpdatables) {
            entity.onUpdate(ev);
        }
    }
    
    public void callRender(final RenderEvent ev) {
        for (final Renderable entity : mRenderables) {
            entity.onRender(ev);
        }
    }
    
    public void callDestroy() {
        for (final DestroyPair pair : mDestroyables) {
            pair.mEntity.onDestroy(pair.mEvent);
            removeUpdatable(pair.mEntity.getUpdatable());
            removeRenderable(pair.mEntity.getRenderable());
        }
        
        mDestroyables.clear();
    }
    
    // Singleton
    private static GameManager inst;
    public static GameManager instance() {
        if (inst == null) inst = new GameManager();
        return inst;
    }
}
